package com.sky.controller.user;


import cn.hutool.extra.qrcode.QrCodeUtil;
import com.sky.result.Result;
import com.sky.service.user.UserOrderService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.*;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import io.lettuce.core.dynamic.annotation.Param;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


import javax.servlet.http.HttpServletRequest;
import java.io.File;

@RestController
@Slf4j
@Api(tags = "微信支付功能")
public class PayController {

    @Autowired
    private Config config;

    @Autowired
    private NotificationConfig notificationConfig;

    @Autowired
    private UserOrderService userOrderService;


    /**
     * 模拟催单
     * @param orderId
     * @return
     */

//    @ApiOperation("催单接口")
//    @GetMapping("{orderId}")
//    public Result reminder( Long orderId) {//传入的是订单id
//        log.info("用户开始催单了");
//        String s = userOrderService.cuiDan(orderId);
//        return Result.success(s);
//    }

    /**
     * 用于模拟用户支付
     * @param num
     * @return
     */
    @GetMapping("/psySuc")
    public Result moNiZhifu(String num) {
        log.info("模拟用户支付成功，通知前端");
        userOrderService.paySuccess(num);
        return Result.success();
    }


    /**
     * 支付回调（监听）
     * 我要提供的接口，微信支付成功会调取这个接口，然后我解析这里的东西！目的就是拿到订单号，确定支付成功
     * 这个是微信写的代码，不是自己写的
     * http://localhost:8080/vx/notiy 微信是访问不了的
     * 所有外网的ip都是一样的 也访问不到
     * 在测试环境的时候（需要内网穿透工具，可以建立通道 ）
     *
     * @return
     */
    @PostMapping("/wx/notify")  //请求微信要求的，路径我自己定义的
    public String VxNotify(@RequestBody String body, HttpServletRequest request)//body随便取的名字
    {
        log.info("收到微信回调消息");
        String weChatSignature = request.getHeader("Wechatpay=Signature");
        String wechatPaySerial = request.getHeader("Wechatpay=Serial");
        String wechatpayNoce = request.getHeader("Wechatpay=Noce");
        String wechatTimestamp = request.getHeader("Wechatpay=Timestamp");

        //构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder().serialNumber(wechatPaySerial).nonce(wechatpayNoce)
                .signature(weChatSignature).timestamp(wechatTimestamp).body(body).build();


        //初始化 NotificationParser   这是微信写好的
        NotificationParser notificationParser = new NotificationParser(notificationConfig);
        Transaction transaction = notificationParser.parse(requestParam, Transaction.class);//解析成Transaction.class类 选择wachat.pay
        String outTradeNo = transaction.getOutTradeNo();//拿订单号
        log.info("订单支付成功，今夕后续处理，订单号是{}", outTradeNo);
        //todo 后续订单相关操作，改支付状态，发货，，，等等,根据特务需求处理
        userOrderService.paySuccess(outTradeNo);
        //处理成功，返回 200 ok 状态，这是要求的，不能给我自己写的Result 回去
        return ResponseEntity.status(HttpStatus.OK).toString();//是微信要求这么写的



    }

    @ApiOperation("新增支付公共")
    @GetMapping("/wxpay")
    public Result pay() {
        //核心思想，通过http调用微信的native下单接口
        NativePayService payService = new NativePayService.Builder().config(config).build();
        //构造参数
        PrepayRequest request = new PrepayRequest();
        request.setOutTradeNo("233333211111111");//支付流水号(订单号)
        request.setDescription("iphone 16 512G");//商品描述
        //http://6c967853.r3.cpolar.top/vx/notify 这是http://6c967853.r3.cpolar.top 外网提供的地址 会转成内网的8080
        // vx/notify是我的请求路径   如果没收到，
        request.setNotifyUrl("http://6c967853.r3.cpolar.top/vx/notify");   // 通知地址 我给的地址（回调地址）互联网能访问的地址
        request.setAppid("wx0ca99a203b1e9943");
        request.setMchid("1561414331");//商户id

        Amount amount = new Amount();//用notivepay里的
        amount.setTotal(1); //支付1分
        amount.setCurrency("CNY");//人民币
        request.setAmount(amount);//金额
        PrepayResponse response = payService.prepay(request);
        String codeUrl = response.getCodeUrl();
        QrCodeUtil.generate(codeUrl, 800, 800, new File("D://微信支付码.jpg"));

        return Result.success();
    }

    /**
     * 查询支付订单
     *
     * @param num
     * @return
     */
    @GetMapping("/query")
    public Result query(String num) {
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();//用用notivepay里的
        request.setMchid("1561414331");//商户id
        request.setOutTradeNo(num);//流水号，可以前端传过来

        // 查询支付成功否：http://localhost:8080/query?num=233333211111111
        NativePayService payService = new NativePayService.Builder().config(config).build();
        Transaction transaction = payService.queryOrderByOutTradeNo(request);

        return Result.success(transaction);
    }

    /**
     * 发起退款
     * 可以看微信支付 接口文档 （可以照着写，按照示例可以自己写）
     *
     * @return
     */
    @GetMapping("/refound") //方便测试写get请求
    public Result result() {
        RefundService refundService = new RefundService.Builder().config(config).build();

        CreateRequest createRequest = new CreateRequest();
        //构造退款参数
        createRequest.setNotifyUrl("ttp://6c967853.r3.cpolar.top/vx/notify");//退款路径
        createRequest.setOutTradeNo("233333211111111");//商户订单号
        createRequest.setOutRefundNo("9999233333211111111");//退款订单号 没有 暂时随便写一个
        createRequest.setReason("就是要退");//可以不写

        AmountReq amountReq = new AmountReq();
        amountReq.setCurrency("CNY");//币种
        amountReq.setTotal(1l);//原订单金额
        createRequest.setAmount(amountReq);
      //Native支付 在微信支付 退款需要的参数 文档有写
        Refund refund = refundService.create(createRequest);

        return Result.success(refund);
    }

}
